Skip to content

feat(v2): Ultra mode toggle — proactive delegation for every model/effort - #1209

Merged
Wibias merged 11 commits into
lidge-jun:devfrom
dbc-hbin:codex/ultra-mode-toggle
Aug 12, 2026
Merged

feat(v2): Ultra mode toggle — proactive delegation for every model/effort#1209
Wibias merged 11 commits into
lidge-jun:devfrom
dbc-hbin:codex/ultra-mode-toggle

Conversation

@dbc-hbin

@dbc-hbin dbc-hbin commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an Ultra mode control that enables codex-rs's Proactive multi-agent delegation policy for every model and every reasoning effort, not just native ultra-effort turns. It exposes the upstream features.multi_agent_v2.multi_agent_mode_hint_text config key through OCX's existing v2 config editor, management API, CLI, and the Subagents GUI.

How it works

Upstream codex-rs derives the multi-agent policy from effort: ultraMultiAgentMode::Proactive, everything else → ExplicitRequestOnly (core/src/session/multi_agents.rs). A configured multi_agent_mode_hint_text overrides that derivation entirely and injects the configured text as the <multi_agent_mode> developer message. Verified live: with the hint set, max/high sessions receive the Proactive prompt and collaboration__spawn_agent actually spawns sub-agents.

Note: the toggle does not change reasoning effort — it changes the delegation prompt policy. The GUI sublabel says so explicitly.

Changes

  • src/codex/features.ts — generalized the v2 string-field reader/writer and added getMultiAgentModeHintText / setMultiAgentModeHintText. Handles all three TOML encodings (dedicated table, inline table, bare-boolean upgrade) with EOL preservation, matching subagent_developer_instructions.
  • src/server/management/agent-settings-routes.tsGET /api/v2 returns multiAgentModeHintText; PUT accepts string | null. Empty/whitespace strings are rejected (a present empty override would suppress even the ultra-derived Proactive message upstream).
  • src/cli/v2.tsocx v2 mode-hint <text|--clear> plus a status line.
  • gui/ — Ultra mode switch + editable text + "Restore preset" on the Subagents page (i18n: en/ko/ja/ru/zh/de/tr/zh-TW). Switch is disabled until multi_agent_v2 is enabled.
  • tests/codex-v2-gate.test.ts — reader/writer encodings, clear semantics, inline-table tricky values (}, quotes), bare-boolean upgrade, API GET/PUT/400 validation, CLI round-trip.

Validation

  • Rebased onto current dev (e8db4e036); zh-TW locale keys added to satisfy the new parity guard.
  • bun x tsc --noEmit (server + gui) passes
  • bun run lint (gui) passes
  • bun test tests/codex-v2-gate.test.ts tests/management-client-config-route.test.ts — 141 pass
  • GUI suite: 768 pass / 0 fail (includes locale-parity for zh-TW)
  • Full suite: core PR test files pass in isolation; full parallel run is subject to pre-existing timing flakes in unrelated files (test-home-guard, etc.) that pass when run individually.

UI Screenshot

Ultra mode toggle on the Subagents page (switch + description + editor):

Ultra mode toggle

Summary by CodeRabbit

  • New Features
    • Added Sub-Agent Ultra Mode with an enable/disable toggle and editable delegation guidance.
    • Added preset restoration, save confirmation, load-retry controls, and prerequisite messaging.
    • Added CLI commands to view, set, and clear the multi-agent mode hint.
    • Added API support for reading, updating, and clearing Ultra Mode guidance.
  • Localization
    • Added Ultra Mode translations in eight languages.
  • Validation
    • Added validation and clear error messages for invalid or empty guidance text.
  • Documentation
    • Documented Ultra Mode configuration and CLI usage.

UI Screenshot

Ultra mode toggle on the Subagents page (switch + description + editor):

Ultra mode toggle

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the enhancement New feature or request label Aug 7, 2026
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change adds Ultra Mode hint-text configuration across Codex persistence, the /api/v2 management API, the V2 CLI, and the subagent GUI. It adds validation, TOML handling, localized controls, preset restoration, retry handling, capability probing, and end-to-end tests.

Changes

Ultra Mode delegation settings

Layer / File(s) Summary
V2 string-field persistence
src/codex/features.ts, tests/codex-v2-gate.test.ts
Shared readers and writers support multi_agent_mode_hint_text across TOML layouts, multiline values, escaping, clearing, CRLF files, and capability probing. Tests cover parsing, persistence, migration, idempotence, and runtime resolution.
API and CLI settings surfaces
src/server/management/agent-settings-routes.ts, src/cli/v2.ts, src/cli/help.ts, docs-site/src/content/docs/reference/cli/agents.md, docs-site/src/content/docs/reference/configuration/agents.md, tests/codex-v2-gate.test.ts
The API exposes, validates, persists, and returns multiAgentModeHintText. The CLI adds `mode-hint <text
GUI state and persistence wiring
gui/src/pages/use-subagent-delegation.ts, gui/src/pages/Subagents.tsx, gui/src/components/subagents-workspace/SubagentsWorkspace.tsx, gui/tests/multi-agent-guidance.test.tsx
The GUI defines Ultra Mode types, loads settings, saves patches, refreshes state, rejects stale responses, handles errors, supports retries, and forwards state to the workspace.
Ultra Mode controls and localization
gui/src/components/subagents-workspace/SubagentDelegationSection.tsx, gui/src/i18n/*.ts, gui/tests/subagents-ultra-mode.test.tsx
The delegation section adds the V2-gated toggle, editable hint text, preset reset, save-state handling, retry controls, and the canonical preset. Locale catalogs and UI tests cover the new behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: lidge-jun, wibias, chrisae9

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 51.28% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding an Ultra mode toggle for proactive delegation across models and reasoning efforts.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed; the review readiness checklist is complete.

Review readiness checklist

  • ✅ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ✅ My PR is ready for review.

4/4 boxes ticked.

This pull request is already Ready for Review.
The review-ready label marks this PR as ready; review automation runs independently. If no CodeRabbit review appears, comment @coderabbitai review to request one.
Maintainers: @lidge-jun @Ingwannu @Wibias

@github-actions
github-actions Bot marked this pull request as draft August 7, 2026 10:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gui/src/components/subagents-workspace/SubagentDelegationSection.tsx`:
- Around line 127-145: Update SubagentDelegationSection’s Ultra Mode editor to
maintain a local draft of ultraMode.hintText instead of calling onUltraModeSave
from the textarea onChange. Add an explicit Save action or serialized debounced
commit using the draft, pass ultraSaving from Subagents.tsx, and disable the
textarea and preset/save controls while the commit is active; keep the draft
synchronized with management API responses after successful reloads.

In `@gui/src/pages/Subagents.tsx`:
- Around line 31-57: Consolidate the duplicated `/api/v2` fetch logic in
`loadUltraMode` and the mount `useEffect` into one shared loader. Ensure
initial-load failures set `status` to `t("sub.ultraModeLoadFail")`, while
refresh failures invoked by saving propagate to `saveUltraMode` instead of being
swallowed; preserve the existing state updates on successful loads.

In `@src/cli/v2.ts`:
- Around line 131-148: Update the mode-hint argument handling around the verb
=== "mode-hint" branch to preserve the raw supplied text for
setMultiAgentModeHintText. Treat only a missing argument as equivalent to
--clear, reject a present whitespace-only value, and retain leading/trailing
whitespace in nonblank hints so CLI behavior matches the API contract.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ec5671af-c0fb-4a89-842c-42e92cdabde3

📥 Commits

Reviewing files that changed from the base of the PR and between 6d8d9fc and a914681.

📒 Files selected for processing (14)
  • gui/src/components/subagents-workspace/SubagentDelegationSection.tsx
  • gui/src/components/subagents-workspace/SubagentsWorkspace.tsx
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/pages/Subagents.tsx
  • gui/src/pages/use-subagent-delegation.ts
  • src/cli/v2.ts
  • src/codex/features.ts
  • src/server/management/agent-settings-routes.ts
  • tests/codex-v2-gate.test.ts

Comment thread gui/src/pages/Subagents.tsx Outdated
Comment thread src/cli/v2.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a914681d3d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread gui/src/components/subagents-workspace/SubagentDelegationSection.tsx Outdated
Comment thread src/cli/v2.ts Outdated
Comment thread gui/src/i18n/en.ts Outdated
Comment thread gui/src/pages/Subagents.tsx Outdated
Comment thread gui/src/components/subagents-workspace/SubagentDelegationSection.tsx Outdated
Comment thread src/codex/features.ts
@dbc-hbin
dbc-hbin marked this pull request as ready for review August 7, 2026 10:23
@github-actions
github-actions Bot marked this pull request as draft August 7, 2026 10:23

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/codex/features.ts (1)

650-667: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Handle quoted keys before editing a dedicated table.

A config can contain "multi_agent_mode_hint_text" = "old value" or 'multi_agent_mode_hint_text' = "old value" in [features.multi_agent_v2]. editScalarInTable only matches the bare key, and the multiline guard at Line 661 also only matches the bare form. A set operation then inserts a bare duplicate key instead of replacing the existing key. TOML treats these keys as identical, so Codex can no longer parse config.toml.

Match and decode bare and quoted keys consistently in the dedicated-table reader, multiline guard, and writer. Add a regression test for updating and clearing a quoted key.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/codex/features.ts` around lines 650 - 667, Update setV2StringField and
the dedicated-table helpers to recognize bare, double-quoted, and single-quoted
forms of the same key, decoding them consistently for reads, multiline
detection, and edits so existing quoted entries are replaced rather than
duplicated. Preserve support for unquoted keys and null clearing, and add
regression coverage for updating and clearing quoted multi_agent_mode_hint_text
entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gui/src/pages/Subagents.tsx`:
- Around line 34-42: Update loadUltraMode to return the parsed UltraModeState
without calling setUltraMode, and have its callers apply the result only when
the request is still current. Add cancellation, request-generation, or
current-apiBase guarding that covers both mount loads and save-triggered
refreshes, ensuring stale /api/v2 responses never overwrite state for a newer
API server.

---

Outside diff comments:
In `@src/codex/features.ts`:
- Around line 650-667: Update setV2StringField and the dedicated-table helpers
to recognize bare, double-quoted, and single-quoted forms of the same key,
decoding them consistently for reads, multiline detection, and edits so existing
quoted entries are replaced rather than duplicated. Preserve support for
unquoted keys and null clearing, and add regression coverage for updating and
clearing quoted multi_agent_mode_hint_text entries.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f09bb947-49b9-44e0-b92e-b8202a9af59c

📥 Commits

Reviewing files that changed from the base of the PR and between a914681 and b85b95c.

⛔ Files ignored due to path filters (1)
  • docs-site/public/assets/ultra-mode-subagents.png is excluded by !**/*.png
📒 Files selected for processing (8)
  • docs-site/src/content/docs/reference/cli/agents.md
  • docs-site/src/content/docs/reference/configuration/agents.md
  • gui/src/components/subagents-workspace/SubagentDelegationSection.tsx
  • gui/src/components/subagents-workspace/SubagentsWorkspace.tsx
  • gui/src/pages/Subagents.tsx
  • src/cli/v2.ts
  • src/codex/features.ts
  • tests/codex-v2-gate.test.ts

Comment thread gui/src/pages/Subagents.tsx Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b85b95cb45

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/codex/features.ts Outdated
Comment thread gui/src/pages/Subagents.tsx
Comment thread gui/src/components/subagents-workspace/SubagentDelegationSection.tsx Outdated
Comment thread src/cli/v2.ts
Comment thread gui/src/pages/Subagents.tsx Outdated
Comment thread src/codex/features.ts
Comment thread gui/src/components/subagents-workspace/SubagentDelegationSection.tsx Outdated
@dbc-hbin
dbc-hbin marked this pull request as ready for review August 7, 2026 11:35
@github-actions
github-actions Bot marked this pull request as draft August 7, 2026 11:36

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fb8a391591

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/codex/features.ts Outdated
Comment on lines +793 to +794
const probe = probeCodexSupportsModeHint();
if (probe === false) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip the capability probe when clearing the hint

When a user downgrades Codex or shares a CODEX_HOME containing a hint written by a newer build, the old runtime rejects the existing key and cannot start, but this unconditional probe also makes ocx v2 mode-hint --clear and the dashboard's off action refuse to remove it. The newly added capability gate should apply only to non-null writes; null removal is backward-compatible and must remain available as the recovery path.

AGENTS.md reference: src/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

Comment thread src/codex/features.ts Outdated
Comment on lines +383 to +386
// Multi-line basic string: `"""..."""` with escapes.
if (token.startsWith('"""')) {
if (!token.endsWith('"""') || token.length < 6) return null;
return decodeBasicStringBody(token.slice(3, -3));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Implement TOML multiline string semantics

For a valid multiline hint using TOML's opening-newline elision or a line-ending backslash continuation, this new branch delegates to the single-line escape decoder: it retains the normally discarded first newline, and a continuation reaches the default escape case and returns null. Consequently getMultiAgentModeHintText can report text different from what Codex uses—or report an active hint as absent—while the writer then refuses to edit that multiline value. Decode the multiline-only newline and continuation rules before returning the hint.

AGENTS.md reference: src/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

Comment thread src/cli/v2.ts Outdated
Comment on lines +148 to +150
if (value.trim().length === 0 || value.startsWith("-")) {
log.error("v2 mode-hint: pass the hint text, or --clear to unset it.");
return 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept hint text that begins with a hyphen

When the intended prose begins with a hyphen, such as ocx v2 mode-hint "- Delegate independent work early", this condition rejects it even though --clear is the only reserved argument and the documented contract otherwise accepts arbitrary nonblank text. This makes a valid hint impossible to set through the CLI; distinguish the exact reserved flag, or support a -- terminator, instead of rejecting every leading hyphen.

AGENTS.md reference: AGENTS.md:L231-L232

Useful? React with 👍 / 👎.

Comment thread gui/src/pages/Subagents.tsx Outdated
ultraSaving,
onUltraModeSave: patch => { void saveUltraMode(patch); },
ultraLoadFailed,
onUltraModeRetry: () => { void loadUltraMode().catch(() => { setOk(false); setUltraLoadFailed(true); setStatus(t("sub.ultraModeLoadFail")); }); },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear the load error after a successful retry

After the initial /api/v2 request fails, status is set to the Ultra-mode load error and rendered as the page-level red notice; the newly added retry callback only handles rejection, while a successful loadUltraMode() clears ultraLoadFailed but never clears that status. The controls therefore recover while the page continues to claim loading failed until some unrelated save changes the notice. Clear the stale status, and update its tone if needed, when the retry succeeds.

AGENTS.md reference: gui/AGENTS.md:L33-L33

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/codex/features.ts`:
- Around line 832-892: Deduplicate the platform package definitions in
codexNativeBinaryCandidates by extracting one shared array of package name,
target triple, and executable name tuples, including all Windows variants.
Replace the three repeated candidate-building lists in the wrapper-relative,
CODEX_MANAGED_PACKAGE_ROOT, and resolved-command branches with loops over that
shared array, preserving their existing root paths.
- Around line 785-830: Cache the result of probeCodexSupportsModeHint per
resolved runtime.command so repeated setMultiAgentModeHintText requests do not
reread and scan native binaries on the request thread. Reuse the cached boolean
or null result for the same command, while invalidating or distinguishing
entries when the resolved command changes; preserve the existing false rejection
and null fallback behavior.
- Around line 375-396: Update decodeTomlStringToken so multi-line literal and
basic string bodies remove the TOML-required leading newline after stripping
their triple delimiters. Apply the trim directly to the triple-single body and
before calling decodeBasicStringBody for triple-double strings, while preserving
all other decoding and validation behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a10a9305-5c3a-4d56-bf27-2498bca681b5

📥 Commits

Reviewing files that changed from the base of the PR and between b85b95c and fb8a391.

📒 Files selected for processing (12)
  • gui/src/components/subagents-workspace/SubagentDelegationSection.tsx
  • gui/src/components/subagents-workspace/SubagentsWorkspace.tsx
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/pages/Subagents.tsx
  • src/cli/help.ts
  • src/codex/features.ts
  • tests/codex-v2-gate.test.ts

Comment thread src/codex/features.ts Outdated
Comment thread src/codex/features.ts
Comment thread src/codex/features.ts
@dbc-hbin
dbc-hbin marked this pull request as ready for review August 7, 2026 13:32
@github-actions
github-actions Bot marked this pull request as draft August 7, 2026 13:32

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fb8a391591

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/codex/features.ts Outdated
const table = tomlTableBody(content, "features.multi_agent_v2");
if (table !== null) {
const m = table.match(/^\s*subagent_developer_instructions\s*=\s*/m);
const keyRe = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*`, "m");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Support quoted TOML keys before editing the hint

When a valid dedicated table uses the quoted key form "multi_agent_mode_hint_text" = "old", this bare-key regex reports the hint as absent. A subsequent non-null save reaches editScalarInTable, which also misses the quoted assignment and inserts an equivalent bare key, producing a duplicate TOML key that Codex cannot parse; clearing similarly becomes a no-op. Recognize and decode quoted keys before reading, replacing, or removing this field.

AGENTS.md reference: src/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

Comment thread gui/src/pages/Subagents.tsx Outdated
// saveUltraMode can report them against the save action.
const loadUltraMode = useCallback(async (signal?: AbortSignal) => {
const res = await fetch(`${apiBase}/api/v2`, { signal });
const data = await readJsonOrThrow<{ enabled?: boolean; multiAgentModeHintText?: string | null }>(res, t("sub.ultraModeLoadFail"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require an effective V2 surface before enabling Ultra mode

The /api/v2 response also provides multiAgentMode, but this loader ignores it and treats the native feature flag alone as sufficient. In the normal default mode, applyMultiAgentMode preserves upstream V1 pins such as Luna, and after mode v1 followed by ocx v2 on, every catalog entry remains forced to V1; those sessions do not receive this V2-only mode hint even though the dashboard enables the switch and claims every model is covered. Consume the effective surface mode and either require/offer v2 mode or clearly restrict Ultra mode to V2 models.

AGENTS.md reference: gui/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

Comment thread src/codex/features.ts Outdated
Comment on lines +851 to +854
out.push(join(pkgRoot, "node_modules", "@openai", "codex-darwin-arm64", "vendor", "aarch64-apple-darwin", "bin", "codex"));
out.push(join(pkgRoot, "node_modules", "@openai", "codex-darwin-x64", "vendor", "x86_64-apple-darwin", "bin", "codex"));
out.push(join(pkgRoot, "node_modules", "@openai", "codex-linux-x64", "vendor", "x86_64-unknown-linux-musl", "bin", "codex"));
out.push(join(pkgRoot, "node_modules", "@openai", "codex-linux-arm64", "vendor", "aarch64-unknown-linux-musl", "bin", "codex"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Resolve the Windows native binary before probing support

On a normal Windows npm installation, the resolved runtime is a codex.cmd or codex.opencodex-real.cmd wrapper. The probe reads that wrapper and sets sawBinary = true, but this wrapper-discovery block adds only Darwin and Linux native packages; the later realpathSync(command) fallback also derives the package root from the .cmd file's directory rather than from the referenced JS package. It therefore finds no native executable, returns false, and rejects every attempt to enable Ultra mode with the misleading instruction to update Codex even when the installed version supports the key. Add the Windows platform-package candidates using the wrapper's actual npm package location, and do not count script wrappers as inspected native binaries.

Useful? React with 👍 / 👎.

@dbc-hbin
dbc-hbin marked this pull request as ready for review August 8, 2026 02:33
@github-actions
github-actions Bot marked this pull request as draft August 8, 2026 02:33

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fb8a391591

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/codex/features.ts Outdated
Comment on lines +843 to +845
const pathDirs = (process.env.PATH ?? "").split(process.platform === "win32" ? ";" : ":");
for (const dir of pathDirs) {
const wrapper = join(dir, process.platform === "win32" ? "codex.opencodex-real.cmd" : "codex.opencodex-real");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Probe only the selected Codex installation

When CODEX_CLI_PATH or the persisted runtime selects an older Codex while a newer codex.opencodex-real is also on PATH, this unconditional PATH scan adds the newer installation's native binary to the candidates. The probe returns true as soon as that unrelated binary contains the key, so Ultra mode writes multi_agent_mode_hint_text for the selected older runtime, which then rejects the unknown field and cannot start. Derive candidates exclusively from runtime.command (and its own shim metadata/package root) rather than mixing every PATH installation into the capability result.

AGENTS.md reference: src/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

Comment thread src/codex/features.ts
Comment on lines +770 to 771
const tableText = `[features.multi_agent_v2]${eol}${key} = ${encoded}${eol}`;
atomicWriteFile(path, `${content}${suffix}${separator}${tableText}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Recognize dotted-key V2 configuration before appending a table

When a valid Codex config expresses this object with root dotted keys, such as features.multi_agent_v2.enabled = true, none of the preceding dedicated-table, [features] inline-table, or bare-boolean checks recognize it. Enabling Ultra mode therefore appends [features.multi_agent_v2], redefining the table created by the dotted key and making config.toml invalid, so Codex fails at startup. Detect and edit the dotted-key representation or refuse the mutation without writing.

AGENTS.md reference: src/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

Comment on lines +225 to +227
/** Canonical Proactive delegation text mirrored from codex-rs (multi_agent_mode_instructions.rs). */
export const ULTRA_MODE_PRESET =
"Proactive multi-agent delegation is active. Any earlier instruction requiring an explicit user request before spawning sub-agents no longer applies. Use sub-agents when parallel work would materially improve speed or quality. This mode remains active until a later multi-agent mode developer message changes it.";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore the complete proactive delegation preset

This string is labeled as the canonical codex-rs preset, but it differs materially from the repository's existing PROACTIVE_MULTI_AGENT_MODE_TEXT in src/server/responses/collaboration.ts: it omits the instructions not to serialize independent work and to prefer specialist sub-agents with their own tool-capable contexts. Because multi_agent_mode_hint_text replaces the effort-derived message rather than augmenting it, enabling or restoring Ultra mode installs this weaker prompt instead of the native proactive behavior the UI and documentation promise. Keep this preset byte-aligned with the canonical text, ideally from a single shared source.

Useful? React with 👍 / 👎.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The upstream capability is technically real, but this head is not an integration candidate yet.

  • The branch is currently 526 commits behind dev; the readiness checklist correctly leaves the latest-dev box unchecked. Please rebase and resolve the accumulated config/GUI/test overlap before further review.
  • Exact-head CI is red (test 2/4, macOS, gates, and the aggregate ci check). Do not treat the local focused pass as sufficient until the rebased head is green.
  • The current decodeTomlStringToken implementation returns the mandatory first newline inside TOML multiline basic/literal strings. TOML trims the newline immediately following the opening triple quote, so reading a valid multi_agent_mode_hint_text = """ Proactive...""" currently adds a spurious leading newline. Fix both triple-quoted forms and keep a regression that matches TOML semantics.

The product naming, default preset text, GUI switch, and whether OCX should expose this unstable upstream override at all require @lidge-jun's explicit product/UI decision. This review is limited to the stale integration and parser/CI blockers; it is not an approval of the UI direction.

@dbc-hbin
dbc-hbin force-pushed the codex/ultra-mode-toggle branch from fb8a391 to d0affeb Compare August 9, 2026 08:43
@dbc-hbin
dbc-hbin marked this pull request as ready for review August 9, 2026 14:56
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@github-actions
github-actions Bot marked this pull request as draft August 9, 2026 14:56

@Wibias Wibias left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review on current head d8987f59c34686bfad27d3eca3b0d0773e1baf7a.

The previous P2 parser blocker is fixed correctly. scanTomlValueEnd now consumes valid 4- and 5-quote closing runs for both multiline basic and literal TOML strings, and the added regressions verify that the surplus one or two quotes remain part of the decoded hint. I did not find a new code blocker in that fix or in the previously reviewed Ultra-mode implementation.

One integration blocker remains before approval:

  • The branch is currently 1 commit behind dev. Current dev is b8a2e51b81aafec33a4865675d2bb29aa1f9eea1, while this head still has merge base e8db4e0365b12a314d1c08ec2cf81599efe5b2d3. The missing dev commit is #1501 (fix(deepseek): preserve parallel reasoning replay) and appears unrelated to this PR, so the rebase should be low-risk, but the repository readiness contract requires the PR to be on latest dev.
  • Exact-head React Doctor is green. Cross-platform CI for this head is still running at the time of review. After rebasing, the new head needs its own green CI signal.
  • The PR is currently draft and its readiness checklist is reset/unchecked, which matches that integration state.

Please rebase onto current dev, rerun exact-head CI, and request re-review. Assuming that lands cleanly and CI is green, I have no remaining code objection from this review.

@github-actions
github-actions Bot marked this pull request as ready for review August 12, 2026 02:09
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] Acknowledged. PR #1209 is ready for review at d8987f59c34686bfad27d3eca3b0d0773e1baf7a. I will review the current head.


🧠 Learnings used
Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 957
File: .github/workflows/release.yml:430-445
Timestamp: 2026-08-03T19:34:43.041Z
Learning: In `lidge-jun/opencodex/.github/workflows/release.yml`, `workflow_dispatch` intentionally permits both `main` and `preview`. The `preview` branch is the preview release train for preview prereleases, so applying a guard that unconditionally rejects non-default-branch dispatches would break the intended release process. `scripts/release.ts` supplies `expected-sha`; the `expected-sha` input remains optional for deliberate manual maintainer dispatches. Review changes to this workflow separately from pre-existing manual-dispatch hardening unless the change modifies its trust controls.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 969
File: .github/scripts/enforce-pr-target.test.cjs:79-81
Timestamp: 2026-08-03T22:37:56.345Z
Learning: In `.github/scripts/enforce-pr-target.test.cjs`, the test named `strips stale WRONG BRANCH prefix on failure when base is corrected` intentionally captures the `if (mustDraft)` block through its first `core.setFailed(` call. It validates draft-path title cleanup with `shouldStripTitlePrefix`, `titlePrefixedByBot = false`, and `pr.title.slice(TITLE_PREFIX.length)`. It must not be retargeted to the `if (failures.length > 0)` quality-failure branch.
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@github-actions The review-readiness gate is complete for d8987f59c34686bfad27d3eca3b0d0773e1baf7a. I will review PR #1209.


🧠 Learnings used
Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 969
File: .github/scripts/enforce-pr-target.test.cjs:79-81
Timestamp: 2026-08-03T22:37:56.345Z
Learning: In `.github/scripts/enforce-pr-target.test.cjs`, the test named `strips stale WRONG BRANCH prefix on failure when base is corrected` intentionally captures the `if (mustDraft)` block through its first `core.setFailed(` call. It validates draft-path title cleanup with `shouldStripTitlePrefix`, `titlePrefixedByBot = false`, and `pr.title.slice(TITLE_PREFIX.length)`. It must not be retargeted to the `if (failures.length > 0)` quality-failure branch.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 957
File: .github/workflows/release.yml:430-445
Timestamp: 2026-08-03T19:34:43.041Z
Learning: In `lidge-jun/opencodex/.github/workflows/release.yml`, `workflow_dispatch` intentionally permits both `main` and `preview`. The `preview` branch is the preview release train for preview prereleases, so applying a guard that unconditionally rejects non-default-branch dispatches would break the intended release process. `scripts/release.ts` supplies `expected-sha`; the `expected-sha` input remains optional for deliberate manual maintainer dispatches. Review changes to this workflow separately from pre-existing manual-dispatch hardening unless the change modifies its trust controls.

Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 771
File: tests/windows-tray.test.ts:70-75
Timestamp: 2026-07-31T01:24:14.745Z
Learning: For the Windows tray launcher tests in `tests/windows-tray.test.ts`, maintainers consider asserting the exact persisted UTF-16LE launcher bytes a non-blocking test-hardening improvement, not a product defect. The current build-and-BOM coverage is acceptable for the PR; a follow-up is welcome.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 1011
File: tests/routing-profile.test.ts:228-234
Timestamp: 2026-08-05T00:33:48.363Z
Learning: In the opencodex repository, `bun x tsc --noEmit` includes the `tests/` directory and passes on the RI-04 routing policy profiles PR head. Do not report that tests are excluded from TypeScript typechecking without verifying the current TypeScript configuration and command behavior.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 627
File: tests/cursor-native-exec-policy.test.ts:0-0
Timestamp: 2026-07-28T16:02:44.312Z
Learning: In the Cursor native-execution rejection flow, platform-specific message branching was removed in commit b5d5bc52. `tests/cursor-native-exec-policy.test.ts` should validate the unified host-shell-neutral recovery guidance on every platform, including PowerShell 5.1 compatibility, `if ($?)` command chaining, and a maximum of one corrected bridge attempt.

Learnt from: Ingwannu
Repo: lidge-jun/opencodex PR: 503
File: tests/doctor.test.ts:81-113
Timestamp: 2026-07-26T13:27:11.063Z
Learning: For the Windows Orca Codex-home diagnostic, `tests/codex-sync-api.test.ts` is the shared behavioral coverage point: it injects deterministic `OrcaCodexHomeDiagnostic` values into `syncModelsToCodex` and captures log/error channels to exercise both the normal catalog-sync branch and the mismatching external-provider branch. During release hardening, avoid adding test-only platform seams to the full network-heavy `runDoctor` command; command-level doctor and restore-back coverage may be deferred.

Learnt from: chrisae9
Repo: lidge-jun/opencodex PR: 1019
File: src/codex/auth-api.ts:1316-1318
Timestamp: 2026-08-04T19:46:02.271Z
Learning: In the TypeScript Codex account lifecycle, `deleteCodexAccount` tombstones credentials before `saveRuntimeConfig` persists the configuration. This cross-file commit gap predates PR `#1019`. Do not propose a simple compensating credential restore: it can corrupt credential generation and validation metadata. A safe fix requires staged deletion or durable multi-file recovery.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-04T08:02:51.614Z
Learning: In PR `#949`, `src/server/index.ts` must derive both bare native OpenAI discovery rows and account-qualified discovery rows from `NATIVE_OPENAI_MODELS` when `accountSelectors.length > 0`, excluding disabled native slugs. Exact qualified IDs in `config.disabledModels`, such as `team/gpt-5.5`, must also omit that specific qualified discovery row.
⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] Acknowledged. The review-readiness gate is complete for d8987f59c34686bfad27d3eca3b0d0773e1baf7a. I will review PR #1209.


🧠 Learnings used
Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 969
File: .github/scripts/enforce-pr-target.test.cjs:79-81
Timestamp: 2026-08-03T22:37:56.345Z
Learning: In `.github/scripts/enforce-pr-target.test.cjs`, the test named `strips stale WRONG BRANCH prefix on failure when base is corrected` intentionally captures the `if (mustDraft)` block through its first `core.setFailed(` call. It validates draft-path title cleanup with `shouldStripTitlePrefix`, `titlePrefixedByBot = false`, and `pr.title.slice(TITLE_PREFIX.length)`. It must not be retargeted to the `if (failures.length > 0)` quality-failure branch.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 957
File: .github/workflows/release.yml:430-445
Timestamp: 2026-08-03T19:34:43.041Z
Learning: In `lidge-jun/opencodex/.github/workflows/release.yml`, `workflow_dispatch` intentionally permits both `main` and `preview`. The `preview` branch is the preview release train for preview prereleases, so applying a guard that unconditionally rejects non-default-branch dispatches would break the intended release process. `scripts/release.ts` supplies `expected-sha`; the `expected-sha` input remains optional for deliberate manual maintainer dispatches. Review changes to this workflow separately from pre-existing manual-dispatch hardening unless the change modifies its trust controls.

Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 771
File: tests/windows-tray.test.ts:70-75
Timestamp: 2026-07-31T01:24:14.745Z
Learning: For the Windows tray launcher tests in `tests/windows-tray.test.ts`, maintainers consider asserting the exact persisted UTF-16LE launcher bytes a non-blocking test-hardening improvement, not a product defect. The current build-and-BOM coverage is acceptable for the PR; a follow-up is welcome.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 1011
File: tests/routing-profile.test.ts:228-234
Timestamp: 2026-08-05T00:33:48.363Z
Learning: In the opencodex repository, `bun x tsc --noEmit` includes the `tests/` directory and passes on the RI-04 routing policy profiles PR head. Do not report that tests are excluded from TypeScript typechecking without verifying the current TypeScript configuration and command behavior.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 627
File: tests/cursor-native-exec-policy.test.ts:0-0
Timestamp: 2026-07-28T16:02:44.312Z
Learning: In the Cursor native-execution rejection flow, platform-specific message branching was removed in commit b5d5bc52. `tests/cursor-native-exec-policy.test.ts` should validate the unified host-shell-neutral recovery guidance on every platform, including PowerShell 5.1 compatibility, `if ($?)` command chaining, and a maximum of one corrected bridge attempt.

Learnt from: Ingwannu
Repo: lidge-jun/opencodex PR: 503
File: tests/doctor.test.ts:81-113
Timestamp: 2026-07-26T13:27:11.063Z
Learning: For the Windows Orca Codex-home diagnostic, `tests/codex-sync-api.test.ts` is the shared behavioral coverage point: it injects deterministic `OrcaCodexHomeDiagnostic` values into `syncModelsToCodex` and captures log/error channels to exercise both the normal catalog-sync branch and the mismatching external-provider branch. During release hardening, avoid adding test-only platform seams to the full network-heavy `runDoctor` command; command-level doctor and restore-back coverage may be deferred.

Learnt from: chrisae9
Repo: lidge-jun/opencodex PR: 1019
File: src/codex/auth-api.ts:1316-1318
Timestamp: 2026-08-04T19:46:02.271Z
Learning: In the TypeScript Codex account lifecycle, `deleteCodexAccount` tombstones credentials before `saveRuntimeConfig` persists the configuration. This cross-file commit gap predates PR `#1019`. Do not propose a simple compensating credential restore: it can corrupt credential generation and validation metadata. A safe fix requires staged deletion or durable multi-file recovery.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-04T08:02:51.614Z
Learning: In PR `#949`, `src/server/index.ts` must derive both bare native OpenAI discovery rows and account-qualified discovery rows from `NATIVE_OPENAI_MODELS` when `accountSelectors.length > 0`, excluding disabled native slugs. Exact qualified IDs in `config.disabledModels`, such as `team/gpt-5.5`, must also omit that specific qualified discovery row.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-04T00:42:36.462Z
Learning: In PR `#949`, when `codexAccountNamespaces` has visible selectors and canonical OpenAI discovery is enabled, the plain `/v1/models` list must expose bare supported native OpenAI IDs and selector-qualified IDs from the same `NATIVE_OPENAI_MODELS` set, excluding only `disabledNativeSlugs`. A partial persisted catalog must not remove supported bare or qualified IDs from raw discovery.
⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/codex/features.ts`:
- Around line 825-861: Update tomlTableBodyForStringFields to scan from offset 0
using scanTomlValueEnd, accepting [header] matches only when they occur outside
complete TOML values; continue searching past header-shaped lines inside
multiline strings. In editScalarInTable, ensure the missing-target guard runs
when either table body omits the assignment, preventing insertion into unrelated
content. Add a regression test covering a header-shaped line inside an earlier
multiline string before the real table.
- Around line 1184-1192: Update resolveSelectedCommandPath to support bare
Windows commands by checking each suffix from PATHEXT, including candidates such
as codex.cmd and codex.exe, while preserving direct path handling and existing
PATH lookup behavior. Add regression tests covering bare commands that resolve
to .cmd and .exe files, ensuring unsupported mode hints are not persisted when
resolution fails.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4a1a1b07-3e89-41b9-b287-65f2f792c824

📥 Commits

Reviewing files that changed from the base of the PR and between b8a2e51 and d8987f5.

⛔ Files ignored due to path filters (1)
  • docs-site/public/assets/ultra-mode-subagents.png is excluded by !**/*.png
📒 Files selected for processing (21)
  • docs-site/src/content/docs/reference/cli/agents.md
  • docs-site/src/content/docs/reference/configuration/agents.md
  • gui/src/components/subagents-workspace/SubagentDelegationSection.tsx
  • gui/src/components/subagents-workspace/SubagentsWorkspace.tsx
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/tr.ts
  • gui/src/i18n/zh-TW.ts
  • gui/src/i18n/zh.ts
  • gui/src/pages/Subagents.tsx
  • gui/src/pages/use-subagent-delegation.ts
  • gui/tests/multi-agent-guidance.test.tsx
  • gui/tests/subagents-ultra-mode.test.tsx
  • src/cli/help.ts
  • src/cli/v2.ts
  • src/codex/features.ts
  • src/server/management/agent-settings-routes.ts
  • tests/codex-v2-gate.test.ts

Comment thread src/codex/features.ts
Comment on lines +825 to +861
/**
* A table body scanner that skips complete TOML values before recognizing the
* next header. Unlike the legacy line scanner, bracket-shaped prose inside a
* multi-line string cannot truncate the table.
*/
function tomlTableBodyForStringFields(content: string, header: string): string | null {
const escaped = escapeRegExp(header);
const match = new RegExp(`^\\s*\\[${escaped}\\]\\s*(?:#.*)?$`, "m").exec(content);
if (!match) return null;
const newline = content.indexOf("\n", match.index + match[0].length);
if (newline === -1) return "";
const bodyStart = newline + 1;
let lineStart = bodyStart;
while (lineStart < content.length) {
let cursor = lineStart;
while (content[cursor] === " " || content[cursor] === "\t") cursor++;
if (content[cursor] === "[") return content.slice(bodyStart, lineStart);
const lineEnd = content.indexOf("\n", cursor);
const boundedEnd = lineEnd === -1 ? content.length : lineEnd;
let keyEnd = cursor;
if (content[keyEnd] === '"' || content[keyEnd] === "'") {
keyEnd = scanTomlValueEnd(content, keyEnd);
} else {
const keyMatch = /^[A-Za-z0-9_.-]+/.exec(content.slice(keyEnd, boundedEnd));
if (keyMatch) keyEnd += keyMatch[0].length;
}
while (content[keyEnd] === " " || content[keyEnd] === "\t") keyEnd++;
if (content[keyEnd] === "=" && keyEnd < boundedEnd) {
const valueEnd = scanTomlValueEnd(content, keyEnd + 1);
const nextLine = content.indexOf("\n", valueEnd);
lineStart = nextLine === -1 ? content.length : nextLine + 1;
} else {
lineStart = lineEnd === -1 ? content.length : lineEnd + 1;
}
}
return content.slice(bodyStart);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== both header lookups in features.ts =="
rg -nP --type=ts -C6 'function tomlTableBodyForStringFields|function tomlTableBody\b' src/codex/features.ts

echo
echo "== every caller that depends on the header anchor =="
rg -nP --type=ts -C3 'tomlTableBodyForStringFields\(|tomlTableBody\(' src

echo
echo "== does any existing test place a header-shaped line BEFORE the real table? =="
rg -nP -C6 'unrelated|\[prose\]|\[bracketed\]' tests/codex-v2-gate.test.ts

Repository: lidge-jun/opencodex

Length of output: 18134


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== relevant helper implementations =="
sed -n '730,940p' src/codex/features.ts

echo
echo "== exact fixture-related tests and writer paths =="
sed -n '480,605p' tests/codex-v2-gate.test.ts

echo
echo "== structural definitions and call sites =="
rg -n -C3 'function (scanTomlValueEnd|findTomlAssignment|setV2StringField|tomlTableBodyForStringFields|tomlTableBody)\b|tomlTableBodyForStringFields\(|tomlTableBody\(' src/codex/features.ts

Repository: lidge-jun/opencodex

Length of output: 28512


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== scanner and assignment semantics =="
sed -n '500,730p' src/codex/features.ts

echo
echo "== writer implementation around editScalarInTable =="
sed -n '650,760p' src/codex/features.ts

echo
echo "== behavioral probe for the proposed fixture =="
node - <<'JS'
const content = `[unrelated]
note = """
[features.multi_agent_v2]
"""

[features.multi_agent_v2]
enabled = true
multi_agent_mode_hint_text = "old"
`;

function escapeRegExp(value) {
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function legacyBody(content, header) {
  const lines = content.split("\n");
  const escaped = escapeRegExp(header);
  const start = lines.findIndex(l => new RegExp(`^\\s*\\[${escaped}\\]\\s*(?:#.*)?$`).test(l));
  if (start === -1) return null;
  const rest = lines.slice(start + 1);
  const end = rest.findIndex(l => /^\s*\[/.test(l));
  return rest.slice(0, end === -1 ? rest.length : end).join("\n");
}
function scanTomlValueEnd(text, start) {
  let i = start;
  while (i < text.length && (text[i] === " " || text[i] === "\t")) i++;
  const first = text[i];
  const triple = text.slice(i, i + 3);
  if (triple === '"""' || triple === "'''") {
    const quote = triple;
    i += 3;
    while (i < text.length) {
      if (text.slice(i, i + 3) === quote) {
        let run = 3;
        while (i + run < text.length && text[i + run] === quote[0]) run++;
        i += run;
        return i;
      }
      i++;
    }
    return text.length;
  }
  if (first === '"' || first === "'") {
    const quote = first;
    i++;
    while (i < text.length) {
      if (text[i] === quote && (quote === "'" || text[i - 1] !== "\\")) return i + 1;
      i++;
    }
    return text.length;
  }
  let depth = 0;
  let inBasic = false;
  let inLiteral = false;
  while (i < text.length) {
    const ch = text[i];
    if (ch === '"' && !inLiteral && text[i - 1] !== "\\") inBasic = !inBasic;
    else if (ch === "'" && !inBasic) inLiteral = !inLiteral;
    else if (!inBasic && !inLiteral && (ch === "[" || ch === "{")) depth++;
    else if (!inBasic && !inLiteral && (ch === "]" || ch === "}")) {
      if (depth > 0) depth--;
    } else if (!inBasic && !inLiteral && depth === 0 && ch === "#") break;
    else if (!inBasic && !inLiteral && depth === 0 && ch === "\n") break;
    i++;
  }
  return i;
}
function newBody(content, header) {
  const escaped = escapeRegExp(header);
  const match = new RegExp(`^\\s*\\[${escaped}\\]\\s*(?:#.*)?$`, "m").exec(content);
  if (!match) return null;
  const newline = content.indexOf("\n", match.index + match[0].length);
  if (newline === -1) return "";
  const bodyStart = newline + 1;
  let lineStart = bodyStart;
  while (lineStart < content.length) {
    let cursor = lineStart;
    while (content[cursor] === " " || content[cursor] === "\t") cursor++;
    if (content[cursor] === "[") return content.slice(bodyStart, lineStart);
    const lineEnd = content.indexOf("\n", cursor);
    const boundedEnd = lineEnd === -1 ? content.length : lineEnd;
    let keyEnd = cursor;
    if (content[keyEnd] === '"' || content[keyEnd] === "'") {
      keyEnd = scanTomlValueEnd(content, keyEnd);
    } else {
      const keyMatch = /^[A-Za-z0-9_.-]+/.exec(content.slice(keyEnd, boundedEnd));
      if (keyMatch) keyEnd += keyMatch[0].length;
    }
    while (content[keyEnd] === " " || content[keyEnd] === "\t") keyEnd++;
    if (content[keyEnd] === "=" && keyEnd < boundedEnd) {
      const valueEnd = scanTomlValueEnd(content, keyEnd + 1);
      const nextLine = content.indexOf("\n", valueEnd);
      lineStart = nextLine === -1 ? content.length : nextLine + 1;
    } else {
      lineStart = lineEnd === -1 ? content.length : lineEnd + 1;
    }
  }
  return content.slice(bodyStart);
}

const legacy = legacyBody(content, "features.multi_agent_v2");
const current = newBody(content, "features.multi_agent_v2");
console.log(JSON.stringify({
  regexMatchOffset: content.indexOf("[features.multi_agent_v2]"),
  realHeaderOffset: content.lastIndexOf("[features.multi_agent_v2]"),
  legacy,
  current,
  legacyHasEnabled: /^\s*enabled\s*=/m.test(legacy ?? ""),
  currentHasEnabled: /^\s*enabled\s*=/m.test(current ?? "")
}, null, 2));
JS

Repository: lidge-jun/opencodex

Length of output: 13661


🏁 Script executed:

#!/bin/bash
set -euo pipefail

node - <<'JS'
const content = `[unrelated]
note = """
[features.multi_agent_v2]
"""

[features.multi_agent_v2]
enabled = true
multi_agent_mode_hint_text = "old"
`;

function escapeRegExp(value) {
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function scanTomlValueEnd(text, start) {
  let i = start;
  while (i < text.length && (text[i] === " " || text[i] === "\t")) i++;
  const first = text[i];
  if (first === '"' && text[i + 1] === '"' && text[i + 2] === '"') {
    i += 3;
    while (i < text.length) {
      if (text[i] === "\\") { i += 2; continue; }
      if (text[i] === '"' && text[i + 1] === '"' && text[i + 2] === '"') {
        let end = i + 3;
        if (text[end] === '"') {
          end++;
          if (text[end] === '"') end++;
        }
        return end;
      }
      i++;
    }
    return text.length;
  }
  if (first === '"' || first === "'") {
    const quote = first;
    i++;
    while (i < text.length) {
      if (quote === "'" ? text[i] === "'" : text[i] === '"' && text[i - 1] !== "\\") return i + 1;
      i++;
    }
    return text.length;
  }
  while (i < text.length && !/[\s,}\]#]/.test(text[i])) i++;
  return i;
}
function stringAwareBody(content, header) {
  const escaped = escapeRegExp(header);
  const match = new RegExp(`^\\s*\\[${escaped}\\]\\s*(?:#.*)?$`, "m").exec(content);
  if (!match) return null;
  const newline = content.indexOf("\n", match.index + match[0].length);
  if (newline === -1) return "";
  const bodyStart = newline + 1;
  let lineStart = bodyStart;
  while (lineStart < content.length) {
    let cursor = lineStart;
    while (content[cursor] === " " || content[cursor] === "\t") cursor++;
    if (content[cursor] === "[") return content.slice(bodyStart, lineStart);
    const lineEnd = content.indexOf("\n", cursor);
    const boundedEnd = lineEnd === -1 ? content.length : lineEnd;
    let keyEnd = cursor;
    if (content[keyEnd] === '"' || content[keyEnd] === "'") {
      keyEnd = scanTomlValueEnd(content, keyEnd);
    } else {
      const keyMatch = /^[A-Za-z0-9_.-]+/.exec(content.slice(keyEnd, boundedEnd));
      if (keyMatch) keyEnd += keyMatch[0].length;
    }
    while (content[keyEnd] === " " || content[keyEnd] === "\t") keyEnd++;
    if (content[keyEnd] === "=" && keyEnd < boundedEnd) {
      const valueEnd = scanTomlValueEnd(content, keyEnd + 1);
      const nextLine = content.indexOf("\n", valueEnd);
      lineStart = nextLine === -1 ? content.length : nextLine + 1;
    } else {
      lineStart = lineEnd === -1 ? content.length : lineEnd + 1;
    }
  }
  return content.slice(bodyStart);
}
function findAssignment(text, key) {
  const match = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=.*$`, "m").exec(text);
  return match ? match[0] : null;
}
function editScalarInTable(source, table, key, encoded) {
  const lines = source.split(/\r?\n/);
  const headerRe = new RegExp(`^\\s*\\[${table.replace(/\./g, "\\.")}\\]\\s*(?:#.*)?$`);
  const headerIdx = lines.findIndex(l => headerRe.test(l));
  let end = lines.length;
  for (let i = headerIdx + 1; i < lines.length; i++) {
    if (/^\s*\[/.test(lines[i])) { end = i; break; }
  }
  for (let i = headerIdx + 1; i < end; i++) {
    if (findAssignment(lines[i], key)) {
      lines[i] = `${key} = ${encoded}`;
      return lines.join("\n");
    }
  }
  lines.splice(headerIdx + 1, 0, `${key} = ${encoded}`);
  return lines.join("\n");
}

const body = stringAwareBody(content, "features.multi_agent_v2");
const legacyBody = content.split("\n").slice(
  content.split("\n").findIndex(l => /^\s*\[features\.multi_agent_v2\]\s*(?:#.*)?$/.test(l)) + 1
).join("\n").split(/^\s*\[/m)[0];

const edited = editScalarInTable(content, "features.multi_agent_v2", "multi_agent_mode_hint_text", '"new"');

console.log(JSON.stringify({
  stringAwareBody: body,
  targetReadFromStringAwareBody: findAssignment(body ?? "", "multi_agent_mode_hint_text"),
  targetReadFromLegacyBody: findAssignment(legacyBody, "multi_agent_mode_hint_text"),
  failClosedGuardWouldFire: !!findAssignment(body ?? "", "multi_agent_mode_hint_text") &&
    !findAssignment(legacyBody, "multi_agent_mode_hint_text"),
  edited
}, null, 2));
JS

Repository: lidge-jun/opencodex

Length of output: 509


🏁 Script executed:

nl -ba src/codex/features.ts | sed -n '670,715p;824,930p'

Repository: lidge-jun/opencodex

Length of output: 193


Resolve the header anchor outside multiline values

At src/codex/features.ts:832, the regex can match [features.multi_agent_v2] inside an earlier multiline string. The scanner then starts at the false header and returns only the string terminator, so getV2StringField misses the real field.

The writer also fails closed incorrectly. At src/codex/features.ts:922-925, both bodies omit the target assignment, so the guard does not run. editScalarInTable then inserts the replacement into the unrelated multiline string instead of the real table, which can corrupt the TOML document.

Scan from offset 0 with the same string-aware value scanner and accept a header only outside a complete TOML value. Add a regression test with a header-shaped line before the real table.

🧰 Tools
🪛 ast-grep (0.45.1)

[warning] 831-831: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^\\s*\\[${escaped}\\]\\s*(?:#.*)?$, "m")
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)

🪛 OpenGrep (1.26.0)

[ERROR] 832-832: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)


[ERROR] 848-848: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/codex/features.ts` around lines 825 - 861, Update
tomlTableBodyForStringFields to scan from offset 0 using scanTomlValueEnd,
accepting [header] matches only when they occur outside complete TOML values;
continue searching past header-shaped lines inside multiline strings. In
editScalarInTable, ensure the missing-target guard runs when either table body
omits the assignment, preventing insertion into unrelated content. Add a
regression test covering a header-shaped line inside an earlier multiline string
before the real table.

Comment thread src/codex/features.ts
Comment on lines +1184 to +1192
/** Resolve only the selected bare command against PATH; never enumerate peers. */
function resolveSelectedCommandPath(command: string): string | null {
if (command.includes("/") || command.includes("\\")) return existsSync(command) ? resolve(command) : null;
for (const dir of (process.env.PATH ?? "").split(delimiter).filter(Boolean)) {
const candidate = join(dir, command);
if (existsSync(candidate)) return candidate;
}
return null;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== how runtime.command is produced =="
rg -nP --type=ts -C6 '\bcommand\s*[:=]' src/codex/runtime.ts | head -120

echo
echo "== any PATHEXT / .cmd / .exe awareness in runtime resolution =="
rg -nP --type=ts -C4 'PATHEXT|\.cmd|\.exe|win32' src/codex/runtime.ts src/codex/features.ts

echo
echo "== existing PATH-scan helpers elsewhere in the repo =="
ast-grep run --lang typescript --pattern 'process.env.PATH ?? $_' src | head -40

Repository: lidge-jun/opencodex

Length of output: 10027


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== feature gate call chain and candidate construction =="
sed -n '1000,1215p' src/codex/features.ts

echo
echo "== runtime candidate resolution and platform checks =="
sed -n '280,380p' src/codex/runtime.ts
sed -n '520,590p' src/codex/runtime.ts

echo
echo "== tests covering Windows runtime commands and feature probing =="
rg -n -C8 --type=ts 'codexNativeBinaryCandidates|resolveSelectedCommandPath|multi_agent_mode_hint_text|platform.*win32|codex\.cmd|codex\.exe' tests src/codex

echo
echo "== exact call sites for the selected-command resolver =="
rg -n -C10 --type=ts 'resolveSelectedCommandPath|codexNativeBinaryCandidates|probeCodexSupportsModeHint' src/codex/features.ts

Repository: lidge-jun/opencodex

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path

features = Path("src/codex/features.ts").read_text()
runtime = Path("src/codex/runtime.ts").read_text()

needles = [
    "function resolveSelectedCommandPath",
    "function codexNativeBinaryCandidates",
    "function probeCodexSupportsModeHint",
    "function setMultiAgentModeHintText",
    "resolveSelectedCommandPath(",
]
for needle in needles:
    print(f"== {needle} in src/codex/features.ts ==")
    lines = features.splitlines()
    for i, line in enumerate(lines, 1):
        if needle in line:
            for j in range(max(1, i-8), min(len(lines), i+35)+1):
                print(f"{j}: {lines[j-1]}")
            print()

print("== pathCandidates/probeVersion in src/codex/runtime.ts ==")
lines = runtime.splitlines()
for needle in ("function pathCandidates", "function probeVersion", "function shimCandidates"):
    for i, line in enumerate(lines, 1):
        if needle in line:
            for j in range(max(1, i-5), min(len(lines), i+45)+1):
                print(f"{j}: {lines[j-1]}")
            print()
PY

Repository: lidge-jun/opencodex

Length of output: 22761


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== runtime resolution order and persisted/environment behavior =="
sed -n '530,575p' src/codex/runtime.ts
sed -n '240,285p' src/codex/runtime.ts
rg -n -C8 --type=ts 'CODEX_CLI_PATH|persisted.*command|resolveAndPersistCodexRuntime|isSpawnableCodexCandidate' src/codex/runtime.ts tests/codex-v2-gate.test.ts

echo
echo "== focused capability-probe tests =="
sed -n '590,680p' tests/codex-v2-gate.test.ts
sed -n '1660,1700p' tests/codex-v2-gate.test.ts

echo
echo "== platform candidate validation =="
rg -n -C12 --type=ts 'function isSpawnableCodexCandidate|isSpawnableCodexCandidate' src/codex/runtime.ts

Repository: lidge-jun/opencodex

Length of output: 25506


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import PurePosixPath

def feature_resolve(command, path, existing):
    if "/" in command or "\\" in command:
        return command if command in existing else None
    for directory in filter(None, path.split(";")):
        candidate = f"{directory}/{command}"
        if candidate in existing:
            return candidate
    return None

def runtime_path_candidates(path):
    out = []
    for directory in filter(None, path.split(";")):
        out.extend([f"{directory}/codex.exe", f"{directory}/codex.cmd"])
    return list(dict.fromkeys(out))

existing = {r"C:\bin/codex.cmd", r"C:\bin/codex.exe"}
print("feature resolver with bare command:", feature_resolve("codex", r"C:\bin", existing))
print("runtime resolver candidates:", runtime_path_candidates(r"C:\bin"))
print("feature resolver with selected .cmd:", feature_resolve("C:\\bin\\codex.cmd", r"C:\bin", existing))
PY

Repository: lidge-jun/opencodex

Length of output: 312


Resolve bare Windows commands with PATHEXT.

When runtime.command is bare codex, resolveSelectedCommandPath checks only PATH\codex. This occurs for CODEX_CLI_PATH, persisted runtime state, or fallback selections; normal Windows PATH discovery already returns codex.exe or codex.cmd. If only codex.cmd or codex.exe exists, the resolver returns null, skips wrapper and binary candidates, and probeCodexSupportsModeHint() returns null. Because only false blocks the write, setMultiAgentModeHintText() can still persist an unsupported key. Scan PATHEXT suffixes and add regression tests for bare commands resolving to .cmd and .exe.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/codex/features.ts` around lines 1184 - 1192, Update
resolveSelectedCommandPath to support bare Windows commands by checking each
suffix from PATHEXT, including candidates such as codex.cmd and codex.exe, while
preserving direct path handling and existing PATH lookup behavior. Add
regression tests covering bare commands that resolve to .cmd and .exe files,
ensuring unsupported mode hints are not persisted when resolution fails.

Source: Linters/SAST tools

…el/effort

Expose codex-rs features.multi_agent_v2.multi_agent_mode_hint_text through
the OCX config editor, /api/v2, the ocx v2 CLI, and the Subagents GUI.

The upstream field overrides the effort-derived multi-agent policy (ultra ->
Proactive, else ExplicitRequestOnly) with custom <multi_agent_mode> text, so
any model and any reasoning effort can run the Proactive delegation prompt.

- features.ts: generalize the v2 string-field reader/writer and add
  get/setMultiAgentModeHintText (dedicated table, inline table, bare-boolean
  upgrade, CRLF/EOL preservation).
- agent-settings-routes.ts: GET /api/v2 reports multiAgentModeHintText; PUT
  accepts string|null and rejects empty/whitespace strings (a present empty
  override would suppress even the ultra-derived Proactive message).
- cli/v2.ts: ocx v2 mode-hint <text|--clear> and status line.
- GUI: Ultra mode switch + editable text + preset restore on the Subagents
  page, disabled until multi_agent_v2 is enabled.
- tests: reader/writer encodings, clear semantics, inline-table tricky values,
  API GET/PUT/400 validation, CLI mode-hint round-trip.
…aft editor, docs

CodeRabbit findings:

- CLI: preserve raw leading/trailing whitespace in mode-hint text; a missing
  argument is a usage error (never a destructive clear); only --clear unsets.
  Reject a present whitespace-only value, matching the API 400 contract.
- features.ts: refuse to edit an existing multi-line TOML string for the hint
  key. scanTomlValueEnd stops at the second quote, so rewriting/removing a
  """...""" value would corrupt the document; convert to single line first.
- GUI: the Ultra mode textarea now keeps a local draft and commits via an
  explicit Save button (remounted on server-value change), so keystrokes are
  never dropped while a PUT is in flight. /api/v2 fetch consolidated into one
  shared loader; initial-load failures surface sub.ultraModeLoadFail instead of
  masquerading as v2-off. V2 requirement is visible text, not only a title attr.
- docs: document ocx v2 mode-hint and the multi_agent_mode_hint_text config key
  (override semantics, --clear, whitespace rejection, v2 requirement).
loadUltraMode now accepts an AbortSignal; the mount effect aborts it on
cleanup so a pending fetch cannot apply state after unmount or after a
refresh superseded it.
…e, GUI retry/clear

Codex + CodeRabbit findings:

- features.ts: scanTomlValueEnd/decodeTomlStringToken now read complete
  multi-line TOML strings ("""...""" and '''...''') so the getter returns
  the real hint instead of an empty string. probeCodexSupportsModeHint checks
  the installed native codex binary for the multi_agent_mode_hint_text key
  (following shim -> npm wrapper -> vendor binary) and refuses writes on older
  builds that reject the unknown config member.
- cli/help.ts: advertise mode-hint in the v2 usage and global synopsis.
- GUI: empty/whitespace hint renders as OFF; clearing stays available when v2
  is disabled (stale hint would otherwise re-activate); load failures surface
  a retry; a successful save clears stale error status and confirms.
- tests: multi-line decode for basic and literal strings.
Rebase onto dev introduced zh-TW as a managed locale with a parity
guard. The Ultra mode keys added by this PR were missing from zh-TW
and would fail locale-parity on the rebased head.
TOML permits up to two quotes immediately inside the closing delimiter
of a multiline string (e.g. """hello"""" → value is hello"). The
scanner stopped at the first triple-quote run, so getMultiAgentModeHintText
returned text different from what Codex parses. Now consume the full valid
closing quote run for both basic and literal multiline strings.

Regression coverage for 4- and 5-quote closing runs in both forms.
@dbc-hbin
dbc-hbin force-pushed the codex/ultra-mode-toggle branch from d8987f5 to 2c11539 Compare August 12, 2026 02:22
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@github-actions[bot] Acknowledged. PR #1209 is marked ready for review at d8987f59c34686bfad27d3eca3b0d0773e1baf7a. The readiness checklist and hygiene checks are complete.

You are interacting with an AI system.

@github-actions
github-actions Bot marked this pull request as draft August 12, 2026 02:23
@dbc-hbin
dbc-hbin marked this pull request as ready for review August 12, 2026 02:24
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] Acknowledged. The readiness gate is complete for 2c115396cacfb40e10014f3ff3cd0eb012b46e5e. I will review PR #1209.


🧠 Learnings used
Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 969
File: .github/scripts/enforce-pr-target.test.cjs:79-81
Timestamp: 2026-08-03T22:37:56.345Z
Learning: In `.github/scripts/enforce-pr-target.test.cjs`, the test named `strips stale WRONG BRANCH prefix on failure when base is corrected` intentionally captures the `if (mustDraft)` block through its first `core.setFailed(` call. It validates draft-path title cleanup with `shouldStripTitlePrefix`, `titlePrefixedByBot = false`, and `pr.title.slice(TITLE_PREFIX.length)`. It must not be retargeted to the `if (failures.length > 0)` quality-failure branch.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 957
File: .github/workflows/release.yml:430-445
Timestamp: 2026-08-03T19:34:43.041Z
Learning: In `lidge-jun/opencodex/.github/workflows/release.yml`, `workflow_dispatch` intentionally permits both `main` and `preview`. The `preview` branch is the preview release train for preview prereleases, so applying a guard that unconditionally rejects non-default-branch dispatches would break the intended release process. `scripts/release.ts` supplies `expected-sha`; the `expected-sha` input remains optional for deliberate manual maintainer dispatches. Review changes to this workflow separately from pre-existing manual-dispatch hardening unless the change modifies its trust controls.

Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 771
File: tests/windows-tray.test.ts:70-75
Timestamp: 2026-07-31T01:24:14.745Z
Learning: For the Windows tray launcher tests in `tests/windows-tray.test.ts`, maintainers consider asserting the exact persisted UTF-16LE launcher bytes a non-blocking test-hardening improvement, not a product defect. The current build-and-BOM coverage is acceptable for the PR; a follow-up is welcome.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 1011
File: tests/routing-profile.test.ts:228-234
Timestamp: 2026-08-05T00:33:48.363Z
Learning: In the opencodex repository, `bun x tsc --noEmit` includes the `tests/` directory and passes on the RI-04 routing policy profiles PR head. Do not report that tests are excluded from TypeScript typechecking without verifying the current TypeScript configuration and command behavior.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 627
File: tests/cursor-native-exec-policy.test.ts:0-0
Timestamp: 2026-07-28T16:02:44.312Z
Learning: In the Cursor native-execution rejection flow, platform-specific message branching was removed in commit b5d5bc52. `tests/cursor-native-exec-policy.test.ts` should validate the unified host-shell-neutral recovery guidance on every platform, including PowerShell 5.1 compatibility, `if ($?)` command chaining, and a maximum of one corrected bridge attempt.

Learnt from: Ingwannu
Repo: lidge-jun/opencodex PR: 503
File: tests/doctor.test.ts:81-113
Timestamp: 2026-07-26T13:27:11.063Z
Learning: For the Windows Orca Codex-home diagnostic, `tests/codex-sync-api.test.ts` is the shared behavioral coverage point: it injects deterministic `OrcaCodexHomeDiagnostic` values into `syncModelsToCodex` and captures log/error channels to exercise both the normal catalog-sync branch and the mismatching external-provider branch. During release hardening, avoid adding test-only platform seams to the full network-heavy `runDoctor` command; command-level doctor and restore-back coverage may be deferred.

Learnt from: chrisae9
Repo: lidge-jun/opencodex PR: 1019
File: src/codex/auth-api.ts:1316-1318
Timestamp: 2026-08-04T19:46:02.271Z
Learning: In the TypeScript Codex account lifecycle, `deleteCodexAccount` tombstones credentials before `saveRuntimeConfig` persists the configuration. This cross-file commit gap predates PR `#1019`. Do not propose a simple compensating credential restore: it can corrupt credential generation and validation metadata. A safe fix requires staged deletion or durable multi-file recovery.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-04T08:02:51.614Z
Learning: In PR `#949`, `src/server/index.ts` must derive both bare native OpenAI discovery rows and account-qualified discovery rows from `NATIVE_OPENAI_MODELS` when `accountSelectors.length > 0`, excluding disabled native slugs. Exact qualified IDs in `config.disabledModels`, such as `team/gpt-5.5`, must also omit that specific qualified discovery row.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-04T00:42:36.462Z
Learning: In PR `#949`, when `codexAccountNamespaces` has visible selectors and canonical OpenAI discovery is enabled, the plain `/v1/models` list must expose bare supported native OpenAI IDs and selector-qualified IDs from the same `NATIVE_OPENAI_MODELS` set, excluding only `disabledNativeSlugs`. A partial persisted catalog must not remove supported bare or qualified IDs from raw discovery.

Learnt from: luvs01
Repo: lidge-jun/opencodex PR: 1195
File: tests/quota-scoring.test.ts:214-226
Timestamp: 2026-08-08T04:13:24.776Z
Learning: In `tests/quota-scoring.test.ts`, `beforeEach` assigns a unique temporary directory to `OPENCODEX_HOME`, and `afterEach` removes that directory. OAuth credentials saved through `src/oauth/store.ts` persist to the current `getConfigDir()/auth.json`, while `getAccountSet()` reloads the file-backed store. Tests in this file do not need an additional OAuth credential cleanup solely to prevent account state from leaking to a later test.
⚠️ Action not completed

No files to review.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

gh pr view 1209 --repo lidge-jun/opencodex \
  --json headRefOid,isDraft,state,updatedAt \
  --jq '{headRefOid, isDraft, state, updatedAt}'

Length of output: 433


@github-actions[bot] Confirmed. PR #1209 is open and ready for review at 2c115396cacfb40e10014f3ff3cd0eb012b46e5e.

The review-readiness gate matches the current PR head.


🧠 Learnings used
Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.
⚠️ Action not completed

No files to review.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Wibias
Wibias merged commit 3713981 into lidge-jun:dev Aug 12, 2026
13 of 19 checks passed

Wibias commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Thank you @dbc-hbin for the work on this PR and for addressing the review feedback.

This is useful because Ultra mode is now a proper OCX control instead of a manual config-only feature. Users can enable proactive sub-agent delegation consistently across models and reasoning-effort levels from the UI, CLI, or API. The added TOML safety checks and regression coverage also make it much safer to expose as a user-facing setting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request review-ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants